package com.ly.heart.service.king;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.google.gson.Gson;
import com.kingdee.bos.webapi.entity.IdentifyInfo;
import com.kingdee.bos.webapi.entity.RepoRet;
import com.kingdee.bos.webapi.sdk.K3CloudApi;
import com.ly.common.exception.CustomException;
import com.ly.common.utils.erp.CommonUtil;
import com.ly.common.utils.erp.KingConstUtil;
import com.ly.heart.domain.KingInventoryEntity;
import com.ly.heart.domain.KingInventoryMaterialEntity;
import com.ly.heart.domain.KingOrgEntity;
import com.ly.heart.domain.king.BaseChildBo;
import com.ly.heart.domain.king.saleInventory.SaleInventoryBo;
import com.ly.heart.domain.king.saleInventory.SaleInventoryDetailBo;
import com.ly.heart.domain.king.saleInventory.SaleInventoryFinanceBo;
import com.ly.heart.domain.request.KingBaseSingleRequest;
import com.ly.heart.domain.response.KingBaseResponse;
import com.ly.heart.domain.response.KingBaseResponseError;
import com.ly.heart.domain.response.KingBaseResponseSuccessEntity;
import com.ly.heart.domain.vo.SaleInventoryKingVo;
import com.ly.heart.service.IKingInventoryMaterialService;
import com.ly.heart.service.IKingInventoryService;
import com.ly.heart.service.IKingOrgService;
import com.ly.heart.util.CurrentUserUtil;
import com.ly.heart.util.KingCommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * 销售出库单推送金蝶
 */
@Component
@Slf4j
public class SaleInventoryPushService {

    @Resource
    private IKingInventoryService iKingInventoryService;
    @Resource
    private IKingInventoryMaterialService iKingInventoryMaterialService;
    @Resource
    private IKingOrgService iKingOrgService;

    public void push ( String id ) {
        KingOrgEntity orgEntity = iKingOrgService.getOne ( new LambdaQueryWrapper<KingOrgEntity> ().eq ( KingOrgEntity :: getOrgId, CurrentUserUtil.getCompanyId () ).eq ( KingOrgEntity :: getIsDisabled, true ) );
        if ( orgEntity == null ) {
            throw new CustomException ( "请先至系统管理中配置金蝶账套！" );
        }
        IdentifyInfo identifyInfo = KingCommonUtil.getIdentifyInfo ( orgEntity );
        K3CloudApi client = new K3CloudApi ( identifyInfo );
        SaleInventoryKingVo saleInventoryKingVo = iKingInventoryService.getInventoryCodeById ( id );
        if ( saleInventoryKingVo == null ) {
            throw new CustomException ( "暂无此单据" );
        }
        if ( saleInventoryKingVo.getIsSend () == KingConstUtil.KING_DATA_IS_SEND_YES ) {
            throw new CustomException ( "该单据已推金蝶，无需重复推送！" );
        }
        SaleInventoryBo saleInventoryBo = assembleInventory ( saleInventoryKingVo );
        try {
            save ( saleInventoryBo, client );
            submit ( saleInventoryBo, client );
            audit ( saleInventoryBo, client );
            updateSendSuccess ( saleInventoryKingVo.getId () );
        } catch ( Exception e ) {
            e.printStackTrace ();
            throw new CustomException ( "销售出库单推送失败，请稍后重试！" );
        }
    }

    private void save ( SaleInventoryBo saleInventoryBo, K3CloudApi client ) throws Exception {
        KingBaseSingleRequest singleRequest = new KingBaseSingleRequest ();
        singleRequest.setModel ( saleInventoryBo );
        String s = JSONObject.toJSONString ( singleRequest );
        log.info ( "销售出库单转JSON->{}", s );
        String resultJson = client.save ( KingConstUtil.SAL_OUTSTOCK, s );
        Gson gson = new Gson ();
        //对返回结果进行解析和校验
        RepoRet repoRet = gson.fromJson ( resultJson, RepoRet.class );
        KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
        StringBuilder sb = new StringBuilder ();
        if ( baseResponse.getIsSuccess () ) {
            List<KingBaseResponseSuccessEntity> successEntities = baseResponse.getSuccessEntitys ();
            sb.append ( "销售出库单-编码为：【" );
            successEntities.forEach ( success -> {
                sb.append ( success.getNumber () ).append ( ";" );
            } );
            sb.append ( "】" );
            log.info ( "{} 推送成功", sb );

        } else {
            List<KingBaseResponseError> errors = baseResponse.getErrors ();
            errors.forEach ( err -> {
                sb.append ( err.getMessage () ).append ( ";" );
            } );
            throw new RuntimeException ( "销售出库单-推送失败：【" + sb + "】" );
        }
    }


    /**
     * 提交采购开票(应付单)到金蝶
     *
     * @param bo
     * @param client
     */
    private void submit ( SaleInventoryBo bo, K3CloudApi client ) throws Exception {
        List<String> strings = new ArrayList<> ();
        strings.add ( bo.getFBillNo () );
        bo.setNumbers ( strings );
        String jsonData = JSON.toJSONString ( bo );
        String resultJson = client.submit ( KingConstUtil.SAL_OUTSTOCK, jsonData );
        Gson gson = new Gson ();
        //对返回结果进行解析和校验
        RepoRet repoRet = gson.fromJson ( resultJson, RepoRet.class );
        KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
        StringBuilder sb = new StringBuilder ();
        if ( baseResponse.getIsSuccess () ) {
            //提交成功
            List<KingBaseResponseSuccessEntity> successEntities = baseResponse.getSuccessEntitys ();
            sb.append ( "销售出库单-编码为：【" );
            successEntities.forEach ( success -> {
                sb.append ( success.getNumber () ).append ( ";" );
            } );
            sb.append ( "】" );
            log.error ( "{} 提交成功", sb );
        } else {
            List<KingBaseResponseError> errors = baseResponse.getErrors ();
            errors.forEach ( err -> {
                sb.append ( err.getMessage () ).append ( ";" );
            } );
            throw new RuntimeException ( "销售出库单提交失败：【" + sb + "】" );
        }
    }

    /**
     * 审核应付单
     *
     * @param bo
     * @param client
     */
    private void audit ( SaleInventoryBo bo, K3CloudApi client ) throws Exception {
        List<String> strings = new ArrayList<> ();
        strings.add ( bo.getFBillNo () );
        bo.setNumbers ( strings );
        String jsonData = JSON.toJSONString ( bo );
        String resultJson = client.audit ( KingConstUtil.SAL_OUTSTOCK, jsonData );
        Gson gson = new Gson ();
        //对返回结果进行解析和校验
        RepoRet repoRet = gson.fromJson ( resultJson, RepoRet.class );
        KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
        StringBuilder sb = new StringBuilder ();
        if ( baseResponse.getIsSuccess () ) {
            //提交成功
            List<KingBaseResponseSuccessEntity> successEntities = baseResponse.getSuccessEntitys ();
            sb.append ( "销售出库单-编码为：【" );
            successEntities.forEach ( success -> {
                sb.append ( success.getNumber () ).append ( ";" );
            } );
            sb.append ( "】" );
            log.error ( "{} 审核成功", sb );
        } else {
            List<KingBaseResponseError> errors = baseResponse.getErrors ();
            errors.forEach ( err -> {
                sb.append ( err.getMessage () ).append ( ";" );
            } );
            throw new RuntimeException ( "销售出库单审核失败：【" + sb + "】" );
        }
    }

    private void updateSendSuccess ( String inventoryId ) {
        boolean update = iKingInventoryService.update ( new LambdaUpdateWrapper<KingInventoryEntity> ().
                set ( KingInventoryEntity :: getIsSend, KingConstUtil.KING_DATA_IS_SEND_YES ).
                eq ( KingInventoryEntity :: getId, inventoryId ) );
        if ( ! update ) {
            throw new CustomException ( "修改销售出库单推送状态失败！" );
        }
    }

    private SaleInventoryBo assembleInventory ( SaleInventoryKingVo saleInventoryKingVo ) {
        SaleInventoryBo bo = new SaleInventoryBo ();
        //1.基础
        bo.setFBillNo ( saleInventoryKingVo.getDocNo () );
        //单据类型
        BaseChildBo docType = new BaseChildBo ().setFNumber ( saleInventoryKingVo.getDocType () );
        bo.setFBillTypeID ( docType );
        //销售组织
        BaseChildBo FSaleOrgId = new BaseChildBo ().setFNumber ( /*saleInventoryKingVo.getPurchaseOrgCode ()*/ "100" );
        bo.setFSaleOrgId ( FSaleOrgId );
        //日期
        bo.setFDate ( CommonUtil.getDateStrFormat ( saleInventoryKingVo.getInventoryTime (), "yyyy-MM-dd" ) );
        //发货组织
        BaseChildBo FStockOrgId = new BaseChildBo ().setFNumber ( /*saleInventoryKingVo.getSendGoodsOrgCode ()*/ "100" );
        bo.setFStockOrgId ( FStockOrgId );
        //客户
        BaseChildBo FCustomerID = new BaseChildBo ().setFNumber ( saleInventoryKingVo.getCustomerCode () );
        bo.setFCustomerID ( FCustomerID );
        //发货部门
        BaseChildBo FDeliveryDeptID = new BaseChildBo ().setFNumber ( saleInventoryKingVo.getSendGoodsDept () );
        bo.setFDeliveryDeptID ( FDeliveryDeptID );
        //库存组
        BaseChildBo FStockerGroupID = new BaseChildBo ().setFNumber ( saleInventoryKingVo.getInventoryGroup () );
        bo.setFStockerGroupID ( FStockerGroupID );
        //仓管员
        BaseChildBo FStockerID = new BaseChildBo ().setFNumber ( saleInventoryKingVo.getManagementCode () );
        bo.setFStockerID ( FStockerID );
        //承运商
        BaseChildBo FCarrierID = new BaseChildBo ().setFNumber ( saleInventoryKingVo.getCarrier () );
        bo.setFCarrierID ( FCarrierID );
        //运输单号
        bo.setFCarriageNO ( saleInventoryKingVo.getTrafficNum () );

        //财务对象
        SaleInventoryFinanceBo financeBo = new SaleInventoryFinanceBo ();
        //结算组织
        BaseChildBo FSettleOrgID = new BaseChildBo ().setFNumber ( /*saleInventoryKingVo.getSettlementOrgCode ()*/ "100" );
        financeBo.setFSettleOrgID ( FSettleOrgID );
        BaseChildBo FSettleCurrID = new BaseChildBo ().setFNumber ( saleInventoryKingVo.getSettlementCurrency () );
        financeBo.setFSettleCurrID ( FSettleCurrID );
        BaseChildBo FSettleTypeID = new BaseChildBo ().setFNumber ( saleInventoryKingVo.getSettlementMethodCode () );
        financeBo.setFSettleTypeID ( FSettleTypeID );
        BaseChildBo FReceiptConditionID = new BaseChildBo ().setFNumber ( saleInventoryKingVo.getTermOfPayment () );
        financeBo.setFReceiptConditionID ( FReceiptConditionID );
        financeBo.setFAllDisCount ( saleInventoryKingVo.getWholeDiscountAmount () );

        bo.setSubHeadEntity ( financeBo );

        //组装明细行
        List<SaleInventoryDetailBo> saleInventoryDetailBos = assembleInventoryDetail ( saleInventoryKingVo.getId () );
        bo.setFEntity ( saleInventoryDetailBos );

        return bo;
    }


    private List<SaleInventoryDetailBo> assembleInventoryDetail ( String inventoryId ) {
        List<SaleInventoryDetailBo> bos = new ArrayList<> ();
        List<KingInventoryMaterialEntity> list = iKingInventoryMaterialService.list ( new LambdaQueryWrapper<KingInventoryMaterialEntity> ().
                eq ( KingInventoryMaterialEntity :: getInventoryId, inventoryId ) );
        list.forEach ( detail -> {
            SaleInventoryDetailBo bo = new SaleInventoryDetailBo ();
            BaseChildBo FMaterialID = new BaseChildBo ().setFNumber ( detail.getMaterialCode () );
            bo.setFMaterialID ( FMaterialID );
            BaseChildBo FUnitID = new BaseChildBo ().setFNumber ( detail.getInventoryUnit () );
            bo.setFUnitID ( FUnitID );

            bo.setFPrice ( detail.getPrice () );
            bo.setFRealQty ( detail.getReceiptsNum () );
            bo.setFMustQty ( detail.getReceivableNum () );
            bo.setFIsFree ( detail.getIsGiveaway () );
            //仓库
            BaseChildBo FStockID = new BaseChildBo ().setFNumber ( detail.getWarehouseCode () );
            bo.setFStockID ( FStockID );

            bos.add ( bo );
        } );
        return bos;
    }

}
